/**
 * @Description:
 * @Author: wyh19
 * @Date: 2021-06-07
 */
import './index.css'
export default {
  install(Vue) {
    function markDiffrent(el, text) {
      if (text === undefined || text === null || text === '') {
        text = '无数据'
      }
      // 创建标志
      const pop = document.createElement('div')
      pop.className = 'v-compare-pop'
      // 创建标志上的小提示气泡
      const tip = document.createElement('div')
      tip.className = 'v-compare-tip'
      tip.style.display = 'none'
      const tipContent = document.createElement('div')
      tipContent.className = 'v-compare-tip-content'
      tipContent.textContent = text
      tip.appendChild(tipContent)
      // 给标志增加点击事件，切换tip显隐
      pop.addEventListener('click', handleClick, true)
      pop.appendChild(tip)
      el.appendChild(pop)
      // 将pop元素缓存在el中，便于销毁时访问到
      el.__pop__ = pop
    }
    // 点击控制隐藏显示
    function handleClick(e) {
      e.stopPropagation()
      if (e.target.className === 'v-compare-pop') {
        const tip = e.target.childNodes[0]
        if (tip.style.display === 'none') {
          tip.style.display = 'block'
        } else {
          tip.style.display = 'none'
        }
      }
    }
    function compareEasyArray(arr1, arr2) {
      // 数组的每一项都是简单类型，且不比较顺序
      const arr1ToString = arr1.sort().join(',')
      const arr2ToString = arr2.sort().join(',')
      return arr1ToString === arr2ToString
    }
    function getArrayMapResult(arr, map) {
      const result = arr.map(item => map[item])
      return result.join(',')
    }
    Vue.directive('compare', {
      componentUpdated(el, binding, vnode) {
        const { value, oldValue, arg, modifiers } = binding
        if (modifiers.map) {
          // map类型的逻辑在此实现
          // 拿到指令更新前后两次的oldFormData
          const oldV = oldValue.oldFormData
          const v = value.oldFormData
          // 拿到map信息
          const map = value.map
          // 比较两次oldFormData，当从无到有时才比对，避免多余的无效比对
          if (!oldV && v) {
            const lastModel = vnode.data.model.value
            const beforeModel = v[arg]
            if (lastModel !== beforeModel) {
              // 直接从map中映射成相应的文本
              markDiffrent(el, map[beforeModel])
            }
          }
        } else if (modifiers.arrayMap) {
          // arrayMap类型的逻辑在此实现
          // 拿到指令更新前后两次的oldFormData
          const oldV = oldValue.oldFormData
          const v = value.oldFormData
          // 拿到map信息
          const map = value.map
          // 比较两次oldFormData，当从无到有时才比对，避免多余的无效比对
          if (!oldV && v) {
            const lastModel = vnode.data.model.value
            const beforeModel = v[arg]
            if (!compareEasyArray(lastModel, beforeModel)) {
              // 直接从map中映射成相应的文本
              markDiffrent(el, getArrayMapResult(beforeModel, map))
            }
          }
        } else {
          // ===原来文本类型比对逻辑保持写法用法不变====
          // oldFormData从无数据到有数据时，才进行比对
          // 避免数据更新过多无效的比对
          if (!oldValue && value) {
            // 进入此if判断时才真正有比对功能
            // 最新的数据，即v-model里现在绑定的值
            const lastModel = vnode.data.model.value
            // 之前的数据，即oldFormData[arg]
            const beforeModel = value[arg]
            // 如果两个数据不相同，这里没有使用!==
            if (lastModel !== beforeModel) {
              // 打上标记
              markDiffrent(el, beforeModel)
            }
          }
        }
      },
      unbind(el) {
        const pop = el.__pop__
        if (pop) {
          pop.removeEventListener('click', handleClick)
        }
      }
    })
  }
}
